-- Datapath do registrador (Mostra descricao estrutural)

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
USE ieee.numeric_std.ALL;
use work.definicoes_gerais.all;


entity data_path is
    generic (num_bits : INTEGER := 32 );
	 Port ( IMEDIATO    : in  STD_LOGIC_VECTOR ((num_bits - 1) downto 0);
           WR_ADDR     : in  reg_geral;
           A_RD_ADDR   : in  reg_geral;
           B_RD_ADDR   : in  reg_geral;
			  SEL_IMM_REG : in  STD_LOGIC;
           RESET       : in  STD_LOGIC;
           STO_REG     : in  STD_LOGIC;
           RD_A        : in  STD_LOGIC;
			  RD_B        : in  STD_LOGIC;
           CLK         : in  STD_LOGIC;
           CARRY       : in  STD_LOGIC;
           ALU_FUNC    : in  operadoresALU;
           REG_OUT_1   : out STD_LOGIC_VECTOR ((num_bits - 1) downto 0);
			  REG_OUT_2   : out STD_LOGIC_VECTOR ((num_bits - 1) downto 0);
           FLAGS       : out STD_LOGIC_VECTOR (7 downto 0));
end data_path;

architecture Behavioral of data_path is
-- Declaracao de componentes usados no datapath
-- ALU
COMPONENT alu
    generic (num_bits : INTEGER := 32 );
	 PORT(
         CARRY       : IN   STD_LOGIC;
			ENTRADA_A   : IN  std_logic_vector((num_bits - 1) downto 0);
         ENTRADA_B   : IN  std_logic_vector((num_bits - 1) downto 0);
         FUNCAO      : IN  operadoresALU;
			FLAGS_OUT_1 : out  STD_LOGIC_VECTOR (7 downto 0); -- 8 Bits de flag
         SAIDA       : OUT  std_logic_vector((num_bits - 1) downto 0)
        );
    END COMPONENT;

-- Bloco de registradores
COMPONENT bloco_registradores
    generic (num_bits : INTEGER := 32 );
	 Port ( CLK       : in   STD_LOGIC;
           RESET     : in   STD_LOGIC;
           STO       : in   STD_LOGIC;
           RD_A      : in   STD_LOGIC;
			  RD_B      : in   STD_LOGIC;
           WR_ADDR   : in   reg_geral;
           A_RD_ADDR : in   reg_geral;
			  B_RD_ADDR : in   reg_geral;
           ENTRADA   : in   STD_LOGIC_VECTOR ((num_bits - 1) downto 0);
			  A_OUT     : out  STD_LOGIC_VECTOR ((num_bits - 1) downto 0);
           B_OUT     : out  STD_LOGIC_VECTOR ((num_bits - 1) downto 0));
    END COMPONENT;

-- Multiplexador
COMPONENT multiplexador
    generic (num_bits : INTEGER := 32 );
	 PORT(
         ENTRADA_A : IN  std_logic_vector((num_bits - 1) downto 0);
         ENTRADA_B : IN  std_logic_vector((num_bits - 1) downto 0);
         SEL       : IN  std_logic;
         SAIDA     : OUT  std_logic_vector((num_bits - 1) downto 0)
        );
    END COMPONENT;

-- Sinais(fios) para conexoes do circuito
SIGNAL SAIDA_ALU       : std_logic_vector((num_bits - 1) downto 0);
SIGNAL SAIDA_A_BLK_REG : std_logic_vector((num_bits - 1) downto 0);
SIGNAL SAIDA_B_BLK_REG : std_logic_vector((num_bits - 1) downto 0);
SIGNAL SAIDA_MUX       : std_logic_vector((num_bits - 1) downto 0);

begin
	-- Instancia bloco de registradores
	blk_reg : component bloco_registradores PORT MAP (
		CLK       => CLK,
		RESET     => RESET,
		STO   	 => STO_REG,
		RD_A      => RD_A,
		RD_B      => RD_B,
		WR_ADDR   => WR_ADDR,
		A_RD_ADDR => A_RD_ADDR,
		B_RD_ADDR => B_RD_ADDR,
		ENTRADA   => SAIDA_ALU,
		A_OUT     => SAIDA_A_BLK_REG,
		B_OUT     => SAIDA_B_BLK_REG
	);
	
	-- Instancia bloco de multiplexador para selecionar para ALU um valor imediato ou outro registrador
	mux_blk : component multiplexador PORT MAP (
		ENTRADA_A => SAIDA_B_BLK_REG,
      ENTRADA_B => IMEDIATO,
      SEL       => SEL_IMM_REG,
      SAIDA     => SAIDA_MUX
	);
	
	-- Instancia ALU
	alu_blk : component alu PORT MAP (
		    CARRY       => CARRY,
			 ENTRADA_A   => SAIDA_A_BLK_REG,
          ENTRADA_B   => SAIDA_MUX,
          FUNCAO      => ALU_FUNC,
			 FLAGS_OUT_1 => FLAGS,
          SAIDA       => SAIDA_ALU
	);
	
	REG_OUT_1 <= SAIDA_A_BLK_REG;
	REG_OUT_2 <= SAIDA_B_BLK_REG;

end Behavioral;

